package com.thot.timyag.web.service;

import java.io.File;
import java.sql.Timestamp;
import java.util.List;
import java.util.Set;

import com.google.common.collect.Lists;
import com.thot.timyag.common.CommonUtil;
import com.thot.timyag.common.FileUtil;
import com.thot.timyag.config.properties.PersistenceProperties;
import com.thot.timyag.core.ApiInfo;
import com.thot.timyag.core.HotDeployContext;
import com.thot.timyag.exceptions.ThotException;
import com.thot.timyag.web.dao.entity.JarInfo;
import com.thot.timyag.web.dao.repository.JarInfoRepository;
import com.thot.timyag.web.pojo.TableResultResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author yangjf
 * @time 2019-06-25 11:58
 */

@Service
public class JarInfoService {
    @Autowired
    private PersistenceProperties persistenceProperties;

    @Autowired(required = false)
    private JarInfoRepository jarInfoRepository;

    @Autowired
    private HotDeployContext context;


    public TableResultResponse<JarInfo> listPage(Integer page, Integer size, String jarWorkSpace, String jarName, String description) {
        if (null != persistenceProperties && persistenceProperties.isEnable()) {
            int startIndex = page > 0 ? (page - 1) * size : 0;
            Pageable pageable = PageRequest.of(startIndex, size);
            if (null == jarName) {
                jarName = "";
            }
            Page<JarInfo> jarInfos;
            if (StringUtils.isEmpty(description)) {
                jarInfos = jarInfoRepository.findByJarWorkspaceAndJarNameLike(jarWorkSpace, "%" + jarName + "%", pageable);
            } else {
                jarInfos = jarInfoRepository.findByJarWorkspaceAndJarNameLikeAndDescriptionLike(jarWorkSpace, "%" + jarName + "%", "%" + description + "%", pageable);
            }
            return new TableResultResponse<>(jarInfos.getTotalElements(), jarInfos.getContent());
        } else {
            throw new ThotException("未启用数据库持久化");
        }
    }

    public JarInfo updateJar(Integer jarId, MultipartFile file, String operater, String description) {
        if (null != persistenceProperties && persistenceProperties.isEnable()) {
            //判断文件是否存在
            JarInfo jarInfo = jarInfoRepository.findById(jarId).get();
            if (null == jarInfo) {
                throw new ThotException("jar不存在");
            }
            if (null != file) {
                File targetFile = null;
                if (file.getOriginalFilename().equals(jarInfo.getJarName())) {
                    //同名文件直接更新
                    targetFile = context.updateJarDependence(file);
                } else {
                    //不同名文件
                    // 先判断新文件名是否已存在
                    List<JarInfo> jarInfos = jarInfoRepository.findByJarNameAndJarWorkspace(file.getOriginalFilename(), jarInfo.getJarWorkspace());
                    if (!CollectionUtils.isEmpty(jarInfos)) {
                        throw new ThotException("jar包已存在，不支持更新");
                    } else {
                        //删除旧文件，保存新文件
                        context.uninstallJarDependence(jarInfo.getJarName());
                        targetFile = context.updateJarDependence(file);
                    }
                }
                jarInfo.setJarSize(FileUtil.getFileSize(targetFile));
                jarInfo.setJarName(file.getOriginalFilename());
            }
            jarInfo.setDescription(description);
            jarInfo.setModifiedTime(new Timestamp(System.currentTimeMillis()));
            jarInfo.setModifiedBy(operater);
            jarInfoRepository.save(jarInfo);
            return jarInfo;
        } else {
            throw new ThotException("未启用数据库持久化");
        }
    }

    public JarInfo addJarInfo(MultipartFile file, String description, String operater, String jarWorkspace) {
        if (null != persistenceProperties && persistenceProperties.isEnable()) {
            //判断是否存在与系统中
            List<JarInfo> jarInfos = jarInfoRepository.findByJarNameAndJarWorkspace(file.getOriginalFilename(), jarWorkspace);
            if (!CollectionUtils.isEmpty(jarInfos)) {
                throw new ThotException("jar包已存在，不可重复添加");
            }
        }
        //保存文件
        File targetFile = context.updateJarDependence(file);
        String fileSize = FileUtil.getFileSize(targetFile);
        JarInfo jarInfo = new JarInfo(fileSize, file.getOriginalFilename(), context.getLibPath(), description, jarWorkspace);
        jarInfo.setCreatedBy(operater);
        if (null != persistenceProperties && persistenceProperties.isEnable()) {
            //持久化到数据库
            jarInfo = jarInfoRepository.save(jarInfo);
        }
        return jarInfo;
    }

    public void deleteJarInfo(String jarName, String jarWorkspace) {
        context.uninstallJarDependence(jarName);
        if (null != persistenceProperties && persistenceProperties.isEnable()) {
            jarInfoRepository.deleteByJarNameAndJarWorkspace(jarName, jarWorkspace);
        }
    }

    public void deleteJarInfo(Integer jarId) {
        if (null != persistenceProperties && persistenceProperties.isEnable()) {
            //查询jarInfo
            JarInfo jarInfo = jarInfoRepository.findById(jarId).get();
            if (null == jarInfo) {
                throw new ThotException("jar包不存在");
            }
            String jarName = jarInfo.getJarName();
            context.uninstallJarDependence(jarName);
            jarInfoRepository.deleteById(jarId);
        } else {
            throw new ThotException("未启用数据库持久化");
        }
    }

    public TableResultResponse listApis(Integer page, Integer size) {
        Set<ApiInfo> apis = context.getRegisterdMappings();
        int total = apis.size();
        if (null != page && null != size) {
            apis = CommonUtil.subSet(apis, page, size);
        }
        return new TableResultResponse<>(total, Lists.newArrayList(apis));
    }
}
